.globl uservec
uservec:
    // sscratch 里预先存有 &trapframe 的地址（main.c 中设置）
    csrrw sp, sscratch, sp
    // 用 a0 保存 trapframe 的地址，同时保存旧 a0

    // 保存所有通用寄存器到 trapframe 中
    sd ra, 0(sp)
    sd gp, 16(sp)
    sd tp, 24(sp)
    sd t0, 32(sp)
    sd t1, 40(sp)
    sd t2, 48(sp)
    sd s0, 56(sp)
    sd s1, 64(sp)
    sd a0, 72(sp)
    sd a1, 80(sp)
    sd a2, 88(sp)
    sd a3, 96(sp)
    sd a4, 104(sp)
    sd a5, 112(sp)
    sd a6, 120(sp)
    sd a7, 128(sp)
    sd s2, 136(sp)
    sd s3, 144(sp)
    sd s4, 152(sp)
    sd s5, 160(sp)
    sd s6, 168(sp)
    sd s7, 176(sp)
    sd s8, 184(sp)
    sd s9, 192(sp)
    sd s10, 200(sp)
    sd s11, 208(sp)
    sd t3, 216(sp)
    sd t4, 224(sp)
    sd t5, 232(sp)
    sd t6, 240(sp)       # 恢复 t6

    // 保存用户程序的 PC（sepc）到 trapframe.epc
    csrr t0, sepc
    sd t0, 248(sp)
    sd sp, 8(sp)               // 原用户态的栈指针

    // 调用 syscall()，传入 trapframe 指针（a0）
    mv a0, sp
    call syscall

    // syscall 的返回值会存在 trapframe.a0 中（72(sp)）
    ld t0, 248(sp)
    addi t0, t0, 4
    csrw sepc ,t0

    // 恢复寄存器
    ld ra, 0(sp)
    ld gp, 16(sp)
    ld tp, 24(sp)
    ld t0, 32(sp)
    ld t1, 40(sp)
    ld t2, 48(sp)
    ld s0, 56(sp)
    ld s1, 64(sp)
    ld a0, 72(sp)
    ld a1, 80(sp)
    ld a2, 88(sp)
    ld a3, 96(sp)
    ld a4, 104(sp)
    ld a5, 112(sp)
    ld a6, 120(sp)
    ld a7, 128(sp)
    ld s2, 136(sp)
    ld s3, 144(sp)
    ld s4, 152(sp)
    ld s5, 160(sp)
    ld s6, 168(sp)
    ld s7, 176(sp)
    ld s8, 184(sp)
    ld s9, 192(sp)
    ld s10, 200(sp)
    ld s11, 208(sp)
    ld t3, 216(sp)
    ld t4, 224(sp)
    ld t5, 232(sp)
    ld t6, 240(sp)
    
    // 恢复 sscratch 中原始 sp（内核栈）
    ld t0, 256(sp)        # trapframe.sstatus
    csrw sstatus, t0
    ld sp, 8(sp)               // 恢复用户态栈指针
    
    //return to user mode
    sret